package top.appx.easysql;

import org.apache.log4j.Logger;
import top.appx.easysql.annotation.Table;
import top.appx.easysql.ex.EasySqlException;
import top.appx.zutil.StringUtil;

import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by john on 2015/12/20.
 */
public class DBUtil {

    public static String getCountSql(String sql){
        return "select count(*) from ("+sql+") as easysql_c";
    }
    public static String getLimitString(String sql,int page,int pageSize){
        return sql +" limit " +(page-1)*pageSize+","+pageSize;
    }


    public static void insertWhere(StringBuilder sql,String whereSql){
        if(sql.indexOf("where") == -1){
            sql.append(" where 1=1 ");
        }
        sql.append(whereSql);
    }
    public static  String transSqlWhere(Class<?> entityClass, List<Object> paramValues, Restrain... restrains){
        String tableName = getTableName(entityClass);
        StringBuilder sql = new StringBuilder("select * from "+tableName+" where 1=1 ");
        transSqlWhere(sql,paramValues,restrains);
        return sql.toString();
    }

    //#region 一些帮助方法

    public static String getTableName(Class<?> entityClass) {
        String tableName = null;
        if (entityClass.isAnnotationPresent(Table.class)) {
            tableName = ((Table) entityClass.getAnnotation(Table.class)).name();
        } else {
            tableName = entityClass.getSimpleName();
        }
        return tableName;
    }


    public static List resultToList(ResultSet rs, Class<?> entityClass) {
        try {
            List list = new ArrayList();
            while (rs.next()) {
                Object entity = entityClass.newInstance();
                Method[] methods = entityClass.getMethods();
                for (Method method : methods) {
                    if (method.getName().startsWith("set")) {
                        String paramName = method.getName().substring(3);
                        Object value = rs.getObject(paramName);
                        if (value != null) {
                            Class typeClass = method.getParameterTypes()[0].getClass();
                            method.invoke(entity, value);
                        }
                    }
                }
                list.add(entity);
            }
            return list;
        } catch (Exception ex) {
            throw new EasySqlException(ex);
        }
    }

    public static  <T> int readId(T entity){
        try {
            Method[] methods = entity.getClass().getMethods();
            for (Method method : methods) {
                if (method.getName().toLowerCase().equals("getid")) {
                    return (Integer) method.invoke(entity);
                }
            }
            return 0;
        }catch (Exception ex){
            throw new EasySqlException(ex);
        }
    }

    public static void transSqlWhere(StringBuilder sql, List paramValues, Restrain... restrains) {
        for (Restrain restrain : restrains) {
            switch (restrain.getRestrainType()) {
                case eq:
                    insertWhere(sql," and " + restrain.getKey() + " = ? ");
                    paramValues.add(restrain.getValues()[0]);
                    break;
                case lt:
                    insertWhere(sql," and " + restrain.getKey() + " < ? ");
                    paramValues.add(restrain.getValues()[0]);
                    break;
                case gt:
                    insertWhere(sql," and " + restrain.getKey() + " > ? ");
                    paramValues.add(restrain.getValues()[0]);
                    break;
                case like:
                    insertWhere(sql," and " + restrain.getKey() + " like ? ");
                    paramValues.add(restrain.getValues()[0]);
                    break;
                case between:
                    insertWhere(sql," and " + restrain.getKey() + " between ? and ? ");
                    paramValues.add(restrain.getValues()[0]);
                    paramValues.add(restrain.getValues()[1]);
                    break;
                case add:
                    insertWhere(sql," and " + restrain.getKey() + " ");
                    if (restrain.getValues() != null) {
                        for (Object obj : restrain.getValues()) {
                            paramValues.add(obj);
                        }
                    }
                    break;
                case in:
                case notin:
                    List<String> arr = new ArrayList<String>();
                    //sql.codePointAt(" and "+restrain.getKey()+" in (");
                    for (Object obj:restrain.getValues()) {
                        arr.add("'" + obj.toString().replaceAll("'","''")+"'");
                    }
                    String ci = " in ";
                    if(restrain.getRestrainType() == RestrainType.notin){
                        ci = " not in ";
                    }
                    insertWhere(sql," and "+restrain.getKey()+" "+ ci +" ("+ StringUtil.join(",",arr)+") ");

                    break;
                case order:
                case orderDesc:


            }
        }
        StringBuilder sqlOrder = new StringBuilder("");
        for (Restrain restrain : restrains) {
            switch (restrain.getRestrainType()) {
                case order:
                case orderDesc:
                    if(sqlOrder.length()==0){
                        sqlOrder.append(" order by "+restrain.getKey());
                    }
                    else{
                        sqlOrder.append(","+restrain.getKey());
                    }
                    if(restrain.getRestrainType() == RestrainType.orderDesc){
                        sqlOrder.append(" desc ");
                    }
                    break;
            }
        }
        sql.append(sqlOrder);
    }
}
